import re
import time
import uuid
import json
import datetime
import random

# from attr.filters import exclude
from rest_framework import serializers
from dateutil.relativedelta import relativedelta
from django.contrib.auth import get_user_model
from core.tools.encryption import hashlib_md5
from chinese_calendar import is_workday
from . import models as my_models
from core.tools.func_utils import funcUtils
from django.conf import settings
from finance_c2c import local_settings
from finance_c2c.settings import Config, ONLINE
from finance_c2c.settings import REGEX_MOBILE, API_DATETIME_FORMAT
from core.tools.func_utils import round_custom
from core.tools.CustomFieldsModelSerializer import DynamicFieldsModelSerializer
from core.wchat.models import RefundRecord
from core.wchat.wx_base import mc

User = get_user_model()


class CoffeeSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.Coffee
        fields = "__all__"


class BannerSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.Banner
        fields = "__all__"


class TradeSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.Trade
        fields = "__all__"


class CoffeeChannelSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.Channel
        exclude = ("key", "secret", "trade", "parent")


# 咖啡机
class CoffeeClientSerializers(DynamicFieldsModelSerializer):
    channel = CoffeeChannelSerializers(many=False)

    class Meta:
        model = my_models.CoffeeClient
        exclude = ("status", )


# 群聊码显示
class GroupQRcodeCoffeeClientSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.CoffeeClient
        fields = ("city", "address", "group_code", "service", "lon", "lat")


# 商品信息
class GoodsSerializers(DynamicFieldsModelSerializer):
    price = serializers.SerializerMethodField(label="价格", help_text="价格")

    def get_price(self, instance):
        return "%.2f" % (instance.price / 100.0)

    class Meta:
        model = my_models.Coffee
        fields = ("id", "name", "image", "pid", "price", "c_type")


# 券信息
class CouponSerializers(DynamicFieldsModelSerializer):
    expire_time = serializers.SerializerMethodField(read_only=True, help_text="到期时间", label="到期时间")
    counts = serializers.IntegerField(read_only=True, label="数量", help_text="数量")
    quota = serializers.SerializerMethodField(read_only=True, label="面值", help_text="面值")
    name = serializers.SerializerMethodField(read_only=True, label="名称", help_text="名称")

    def get_quota(self, instance):
        if isinstance(instance, dict):
            return instance.get("quota") / 100
        else:
            return instance.quota / 100

    def get_expire_time(self, instance):
        return instance.get("expire_time").strftime("%Y-%m-%d")

    def get_name(self, instance):
        if isinstance(instance, dict):
            return instance.get("name")
        else:
            return instance.name

    class Meta:
        model = my_models.CouponInfo
        fields = ("quota", "expire_time", "c_type", "counts", "name", "used", "status")


# 已过期
class UseSerializers(DynamicFieldsModelSerializer):
    use_time = serializers.DateTimeField(read_only=True, format=settings.API_DATE_FORMAT, help_text="到期时间",
                                         label="到期时间")
    create_time = serializers.DateTimeField(read_only=True, format=settings.API_DATETIME_FORMAT, help_text="创建时间",
                                            label="创建时间")
    coupon = CouponSerializers(read_only=True, fields=("id", "name", "expire_time"))

    class Meta:
        model = my_models.UseRecord
        fields = ("id", "use_time", "coupon", "create_time", "status")


# 赠送记录列表
class GiveRecordSerializers(DynamicFieldsModelSerializer):
    create_time = serializers.DateTimeField(read_only=True, format=settings.API_DATETIME_FORMAT, help_text="创建时间",
                                            label="创建时间")
    update_time = serializers.DateTimeField(read_only=True, format=settings.API_DATETIME_FORMAT, help_text="更新时间",
                                            label="更新时间")

    share_mobile = serializers.SerializerMethodField(label="分享人手机号", help_text="分享人手机号")
    receive_mobile = serializers.SerializerMethodField(label="接收人手机号", help_text="接收人手机号")
    quota = serializers.SerializerMethodField(label="额度", help_text="额度")

    def get_share_mobile(self, instance):
        if instance.give_type == 4:
            return "商家赠送"
        else:
            return instance.own_user.mobile[:3] + "****" + instance.own_user.mobile[-4:]

    def get_receive_mobile(self, instance):
        if instance.give_type == 4:
            return "商家赠送"
        else:
            if instance.receive_user:
                return instance.receive_user.mobile[:3] + "****" + instance.receive_user.mobile[-4:]
            else:
                return ""

    def get_create_time(self, instance):
        return instance.update_time.strftime(API_DATETIME_FORMAT)

    def get_quota(self, instance):
        if instance.coupon:
            coupon_id = eval(instance.coupon)[0]
            try:
                return "%.2f" % (my_models.CouponInfo.objects.get(id=coupon_id).quota / 100)
            except Exception as e:
                if instance.c_type == 2:
                    return "6.00"
                else:
                    return "0"
        else:
            if instance.c_type == 2:
                return "6.00"
            else:
                return "0"

    class Meta:
        model = my_models.GiveRecord
        fields = (
            "id", "quota", "num", "create_time", "c_type", "share_mobile", "receive_mobile", "status", "update_time")


# 取消赠送
class CancelGiveRecordSerializers(DynamicFieldsModelSerializer):
    status = serializers.ChoiceField(write_only=True, choices=my_models.GiveRecord.receiveStatus, help_text="接收状态",
                                     label="接收状态")

    def validate_status(self, status):
        if self.instance.status == 2:
            if status == 3:
                return status
            else:
                raise serializers.ValidationError("参数错误")
        raise serializers.ValidationError("状态错误")

    def update(self, instance, validated_data):
        instance.update_status_3()
        return instance

    class Meta:
        model = my_models.GiveRecord
        fields = ("status",)


# 订单列表
class OrderSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    num = serializers.IntegerField(label="数量", help_text="数量")
    create_time = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="订单创建时间")
    coupon = CouponSerializers(fields=("used", "name", "c_type"), many=False)
    payment = serializers.SerializerMethodField(label="实付", help_text="实付")
    cash = serializers.SerializerMethodField(label="应付", help_text="应付")
    show = serializers.SerializerMethodField(label="是否显示领兑换券", help_text="是否显示领兑换券")
    coffee_client = CoffeeClientSerializers(fields=("address", "sign"))

    def get_payment(self, instance):
        return "%.2f" % (instance.payment / 100.0)

    def get_cash(self, instance):
        return "%.2f" % (instance.cash / 100.0)

    def get_show(self, instance):
        if instance.payment == instance.cash:
            return True
        else:
            return False

    class Meta:
        model = my_models.CoffeeOrder
        fields = ("id", "result", "num", "create_time", "goods_name", "coupon", "payment", "show",
                  "coffee_client", "user", "goods_image", "cash", "coffee_make_result", "orderNo")


# 创建订单
class CreateOrdersSerializers(serializers.Serializer):
    c_type = serializers.ChoiceField(label="券类型", help_text="券类型", required=False, allow_null=True,
                                     allow_blank=True,
                                     choices=my_models.CouponInfo.cType)
    num = serializers.IntegerField(label="数量", help_text="数量", required=True, allow_null=False)
    quota = serializers.IntegerField(label="额度", help_text="额度", allow_null=True, default=0)

    pay_type = serializers.IntegerField(label="支付类型", help_text="支付类型", required=True, allow_null=False)
    key = serializers.CharField(label="参数", write_only=True, help_text="小程序码参数", required=True,
                                allow_null=False,
                                allow_blank=False)
    # {coupon_id，数量}
    # cash_coupon = serializers.IntegerField(label="现金券数量", help_text="现金券数量", allow_null=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    invoiced = serializers.IntegerField(write_only=True, default=0)

    class Meta:
        fields = ("c_type", "num", "pay_type", "user", "key", "quota", "invoiced")

    def validate_orderNo(self, orderNo):
        if orderNo:
            if my_models.CoffeeOrder.objects.filter(orderNo=orderNo).exists():
                print(orderNo, '此订单已创建')
                raise serializers.ValidationError("此订单已创建，请前往订单列表中进行支付")
            print("order create success")
        else:
            raise serializers.ValidationError("订单号错误")

    def validate_key(self, key):
        from core.wchat.wx_base import mc
        value = mc.get(key)
        if value:
            value = json.loads(value)
            self.validate_orderNo(value.get("orderNo"))
            print(value, "value")
            return value
        else:
            raise serializers.ValidationError("订单已过期")

    def validate_coffee_client(self, coffee_client):
        try:
            return my_models.CoffeeClient.objects.get(sign=coffee_client)
        except Exception as e:
            raise serializers.ValidationError("咖啡机不在工作区")

    def validate_c_type(self, c_type):
        if c_type:
            if c_type == -2:
                user = self.context["request"].user
                key = f"c_type_{user.id}"
                c_type = mc.get(key)
                if c_type:
                    mc.delete(key)
            user = self.context["request"].user
            quota = self.initial_data.get("quota")
            if not quota:
                queryset = my_models.CouponInfo.objects.filter(user=user, used=False, expired=False, c_type=c_type,
                                                               given=False).order_by("expire_time")
            else:
                queryset = my_models.CouponInfo.objects.filter(user=user, used=False, expired=False, c_type=c_type,
                                                               given=False, quota=int(quota)).order_by("expire_time")
            if queryset.exists():
                setattr(self, "couponInstance", queryset.first())
            else:
                setattr(self, "couponInstance", None)
                # raise serializers.ValidationError("没有合适的优惠券")
            return c_type
        else:
            setattr(self, "couponInstance", None)
            return c_type

    def v_type_c(self, pid, c_type):
        print(c_type, f"c_type={c_type}")
        try:
            coffee = my_models.Coffee.objects.get(pid=pid)
        except Exception as e:
            raise serializers.ValidationError(f"pid error {pid}")
        # ((0, "没使用券"), (1, "免费A"), (2, "立减券"), (3, "兑换券A"), (6, "免费B"), (7, "通用免费券"), (8, "兑换券B"))
        print(c_type, coffee.c_type, "logs")
        if c_type == 6:
            if coffee.c_type == 2:  # 如果是选择的免费券B 并且是用于免费花式
                pass
            else:
                print("此免费券和商品类型不匹配")
                raise serializers.ValidationError("此免费券和商品类型不匹配")
        elif c_type == 8:
            # 如果是选择的免费券A 并且是用于免费美式   coffee.c_type 1 美式 2花式
            if coffee.c_type == 2 and coffee.pid not in my_models.Coffee.coffeeType3:
                pass
            else:
                print("此免费券和商品类型不匹配 兑换券B")
                raise serializers.ValidationError("此免费券和商品类型不匹配")
        elif c_type == 1:
            if coffee.c_type == 1:  # 如果是选择的免费券A 并且是用于免费美式
                pass
            else:
                print("此优惠券和商品类型不匹配2")
                raise serializers.ValidationError("此优惠券和商品类型不匹配。")
        elif c_type == 3:
            if coffee.c_type == 1:  # 如果是选择的免费券A 并且是用于免费美式
                pass
            else:
                print("此优惠券和商品类型不匹配1 兑换券A")
                raise serializers.ValidationError("此优惠券和商品类型不匹配.")
        elif c_type == 7:
            pass
        elif c_type == 11:
            # 811 醇香牛奶、 802 巧克力牛奶
            str_c_type_list = [str(i) for i in my_models.Coffee.coffeeType3]
            if coffee.pid in my_models.Coffee.coffeeType3:  # 如果是选择的免费券C 只适用于醇香牛奶、 802 巧克力牛奶
                pass
            elif coffee.pid in str_c_type_list:
                pass
            else:
                print("此优惠券C和商品类型不匹配 只适用于")
                raise serializers.ValidationError("此优惠券和商品类型不匹配!")

    def validate(self, attrs):
        user = self.context["request"].user
        value = attrs.pop("key")
        attrs.pop("quota")
        pid = value["pid"]  # 商品id
        if self.couponInstance:
            self.v_type_c(pid, self.couponInstance.c_type)
        coffee_client = self.validate_coffee_client(value["vmc"])
        print("pid", pid, "device_type", coffee_client.device_type)
        # coffee = my_models.Coffee.objects.get(pid=pid, device_type=coffee_client.device_type)
        coffee = my_models.Coffee.objects.get(pid=pid)
        attrs["orderNo"] = value["orderNo"]
        attrs["pid"] = pid
        attrs["goods_name"] = coffee.name
        attrs["goods"] = coffee
        attrs["goods_image"] = coffee.image
        attrs["coupon"] = self.couponInstance
        attrs["price"] = coffee.price
        attrs["cash"] = coffee.price * attrs["num"]
        attrs["channel"] = coffee_client.channel
        attrs["coffee_client"] = coffee_client
        print(attrs, "create order c_type info")
        # attrs["out_trade_no"] = uuid.uuid1().hex
        if self.couponInstance:
            # 如果是免费券
            if self.couponInstance.c_type in my_models.CouponInfo.freeCouponType:
                attrs["pay_type"] = 99  # 免支付
                attrs["result"] = 1  # 支付成功
                attrs["pay_time"] = datetime.datetime.now()
                attrs["coffee_make_result"] = 3
            elif self.couponInstance.c_type == 2:  # 如果选择的是立减券
                attrs["payment"] = coffee.price - self.couponInstance.quota
            elif self.couponInstance.c_type == 3:  # 如果选择的是一元喝咖啡券A
                attrs["payment"] = self.couponInstance.quota
            elif self.couponInstance.c_type == 8:  # 如果选择的是一元喝咖啡券B
                attrs["payment"] = self.couponInstance.quota
            elif self.couponInstance.c_type == 4:  # 如果选择的对折券
                attrs["payment"] = round(coffee.price * 0.5)
            elif self.couponInstance.c_type == 9:  # 两元兑换券
                attrs["payment"] = self.couponInstance.quota
            else:
                attrs["payment"] = coffee.price
        else:  # 如果没选择券
            ctype = attrs["c_type"]
            if ctype == 0:  # 没用券 没减一毛活动
                attrs["payment"] = coffee.price
            if ctype == -1:  # 每天减一毛
                attrs["payment"] = coffee.price
                today = datetime.date.today()
                if is_workday(today):
                    queryset = my_models.ReduceMoneyEveryDay.objects.get_last_data(user.id)
                    if queryset.exists():
                        instance = queryset.first()
                        reduce_date = instance.reduce_date
                        # 每天只能减钱买一次
                        if today != reduce_date:
                            money = instance.money
                            if coffee.price < money:
                                attrs["result"] = 1  # 支付成功
                                attrs["pay_time"] = datetime.datetime.now()
                                attrs["coffee_make_result"] = 3
                                attrs["payment"] = 0
                                attrs["pay_type"] = 101
                                # my_models.ReduceMoneyEveryDay.objects.create_data(user.id)
                            else:
                                attrs["payment"] = coffee.price - money

        attrs.pop("c_type")
        return attrs

    def create(self, validated_data):
        print(validated_data, "validated_data")
        instance = my_models.CoffeeOrder.objects.create(**validated_data)
        user = self.context["request"].user
        user.coffee_new_user = False
        user.save()
        if instance.coupon:
            coupon = instance.coupon
            coupon.used = True
            coupon.save()
        if instance.pay_type == 99:
            instance.update_result(pay_type=99)
        if instance.pay_type == 101:  # 每天减一毛免支付
            instance.update_result(pay_type=101)
            my_models.ReduceMoneyEveryDay.objects.create_data(
                user_id=instance.user.id
            )
        if instance.coupon:  # 如果使用了券
            # 先将券占用上
            my_models.UseRecord.objects.create(
                coupon=instance.coupon,
                num=instance.num,
                order=instance,
                user=instance.user,
            )
            # 更新券可用的数量
            instance.coupon.used = True
            instance.coupon.save()
        return instance

    def update(self, instance, validated_data):
        pass


class OrderUpdateSerializers(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    c_type = serializers.ChoiceField(label="券类型", help_text="券类型", required=False, allow_null=True,
                                     allow_blank=True,
                                     choices=my_models.CouponInfo.cType)
    orderNo = serializers.CharField(label="订单号", write_only=True, max_length=64, min_length=0, help_text="订单号",
                                   required=True)

    def validate_c_type(self, c_type):
        # 只针对免费券
        if c_type in my_models.CouponInfo.freeCouponType:
            user = self.context["request"].user
            quota = self.initial_data.get("quota")
            if not quota:
                queryset = my_models.CouponInfo.objects.filter(user=user, used=False, expired=False, c_type=c_type,
                                                               given=False).order_by("expire_time")
            else:
                queryset = my_models.CouponInfo.objects.filter(user=user, used=False, expired=False, c_type=c_type,
                                                               given=False, quota=int(quota)).order_by("expire_time")
            if queryset.exists():
                setattr(self, "couponInstance", queryset.first())
            else:
                # setattr(self, "couponInstance", None)
                raise serializers.ValidationError("没有合适的优惠券")
            return c_type
        else:
            raise serializers.ValidationError("券类型数据请求错误")

    def validate_orderNo(self, orderNo):
        instance = my_models.CoffeeOrder.objects.filter(orderNo=orderNo).first()
        if instance:
            return instance
        else:
            raise serializers.ValidationError("订单不存在")


    def create(self, validated_data):
        instance= validated_data["orderNo"]
        if instance.coupon:  # 如果使用了券
            # 先将券使用记录删除
            my_models.UseRecord.objects.filter(coupon=instance.coupon).delete()
            # 更新券可用的数量
            instance.coupon.used = False
            instance.coupon.save()

        # 更新换券后的逻辑
        my_models.UseRecord.objects.create(
            coupon=self.couponInstance,
            num=1,
            order=instance,
            user=instance.user,
        )
        # 通知技诺制作咖啡
        instance.update_result(pay_type=99)
        # 更新订单数据
        instance.coupon = self.couponInstance
        instance.save()

        # 更新券可用的数量
        instance.coupon.used = True
        instance.coupon.save()
        return instance


    class Meta:
        fields = ("c_type", "user", "orderNo")
        model = my_models.CoffeeOrder

# 更新订单(取消订单)
class UpdateOrdersSerializers(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    result = serializers.ChoiceField(choices=my_models.CoffeeOrder.orderStatus, required=True, write_only=True,
                                     allow_null=False)

    class Meta:
        model = my_models.CoffeeOrder
        fields = ("user", "result")

    def validate_result(self, result):
        if result == 3 and self.instance.result == 0:
            pass
        if result == 3 and self.instance.result == 0:
            return result
        elif result == 4 and self.instance.result == 1:
            return result
        else:
            raise serializers.ValidationError("result传值错误")


# 填写手机号转赠券
class GiveByTelSerializers(serializers.Serializer):
    mobile = serializers.CharField(label="手机号", write_only=True, max_length=11, min_length=11, help_text="手机号",
                                   required=True, error_messages={
            "required": "手机号为必填项",
            "blank": "账号不能为空",
            "max_length": "账号过长",
            "min_length": "账号过短"
        })
    type_num = serializers.ListField(label="类型数量json[{'type':1},{'num':1}]", help_text="类型数量json",
                                     write_only=True)

    def validate_type_num(self, type_num):
        user = self.context["request"].user
        for i in type_num:
            c_type = i.get("type")
            num = i.get("num")
            quota = i.get("quota")
            if not quota:
                quota = 600
            if c_type == 2 or c_type == "2":
                sum_num = my_models.CouponInfo.objects.get_useful_sum(user, c_type, quota=int(quota))
            else:
                sum_num = my_models.CouponInfo.objects.get_useful_sum(user, c_type)
            # sum_num = my_models.CouponInfo.objects.get_useful_sum(user, c_type)
            if sum_num >= num:
                pass
            else:
                raise serializers.ValidationError("没有适合分享的券")
        return type_num

    class Meta:
        fields = ("mobile", "type_num",)

    def validate_mobile(self, mobile):
        user = self.context["request"].user
        if user.mobile == mobile:
            raise serializers.ValidationError("自己不能转发给自己")
        if re.match(REGEX_MOBILE, mobile):
            receive_user, created = my_models.User.objects.get_or_create_user(mobile,
                                                                              coffee_channel=user.coffee_channel)
            if created or receive_user.coffee_new_user:  # 如果用户是新建的，先不接收呢
                status = 2
            else:  # 如果用户存在 就直接给到他账号上
                status = 1
            setattr(self, "receive_user", receive_user)
            setattr(self, "receive_user_status", status)
            user = self.context["request"].user
            if user.id == receive_user.id:
                raise serializers.ValidationError("请填写他人手机号")
            return mobile
        else:
            raise serializers.ValidationError("手机号不合法")

    def create(self, validated_data):
        print("GiveByTelSerializers")
        user = self.context["request"].user
        type_num = validated_data["type_num"]
        status = self.receive_user_status
        receive_user = self.receive_user
        coupon_id_list_base = []
        coupon_list_type = []
        for i in type_num:
            c_type = i.get("type")
            num = i.get("num")
            quota = i.get("quota")
            if not quota:
                quota = 1200
            if c_type == 2 or c_type == "2":
                coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num, quota=quota)
            else:
                coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num)
            # 分享后减少券
            # coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num)
            coupon_id_list_base.extend(coupon_id_list)
            coupon_list_type.append({"coupon_id_list": coupon_id_list, "c_type": c_type})
        for i in coupon_list_type:
            # 创建转赠记录(按券管理的数据对应，创建转赠记录)
            coupon_id_list = i.get("coupon_id_list")
            c_type = i.get("c_type")
            if status == 1:
                my_models.GiveRecord.objects.create_record(coupon_id_list, len(coupon_id_list), user,
                                                           c_type, receive_user=receive_user)
            else:
                my_models.GiveRecord.objects.create_record(coupon_id_list, len(coupon_id_list), user,
                                                           c_type, receive_user=receive_user, status=2)
        # 转赠到接收人头上
        if status == 1:
            my_models.CouponInfo.objects.filter(id__in=coupon_id_list_base).update(user=receive_user, given=False)
        else:
            my_models.CouponInfo.objects.filter(id__in=coupon_id_list_base).update(given=True)
        return validated_data

    def update(self, instance, validated_data):
        pass


# 生成扫码领取的二维码
class GiveRecordUrlSerializers(serializers.Serializer):
    typeSource = (("wchatMini", "小程序"), ("H5", "H5"),)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    type_num = serializers.ListField(label="类型数量json[{'type':1},{'num':1}]", help_text="类型数量json",
                                     write_only=True)
    page = serializers.CharField(label="page", required=True, allow_null=False, error_messages={
        "required": "page为必填项",
        "blank": "page不能为空",
    })
    type_source = serializers.ChoiceField(default="wchatMini", choices=typeSource, label="来源", help_text="来源",
                                          write_only=True)

    # def validate_type_source(self, attrs):
    #     if attrs:
    #         return attrs
    #     else:
    #         return "wchatMini"

    def validate_type_num(self, type_num):
        user = self.context["request"].user
        for i in type_num:
            c_type = i.get("type")
            num = i.get("num")
            quota = i.get("quota")
            if not quota:
                quota = 600
            if c_type == 2 or c_type == "2":
                sum_num = my_models.CouponInfo.objects.get_useful_sum(user, c_type, quota=int(quota))
            else:
                sum_num = my_models.CouponInfo.objects.get_useful_sum(user, c_type)
            if sum_num >= num:
                pass
            else:
                print("没有适合分享的券 小程序码")
                raise serializers.ValidationError("没有适合分享的券")
        return type_num

    def create(self, validated_data):
        user = self.context["request"].user
        type_num = validated_data["type_num"]
        give_record_list = []
        coupon_id_list_base = []
        coupon_list_type = []
        # quota = 0
        for i in type_num:
            c_type = i.get("type")
            num = i.get("num")
            quota = i.get("quota")
            # if not quota:
            #     quota = 600
            if c_type == 2 or c_type == "2":
                if not quota:
                    quota = 600
                coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num, quota=quota)
            else:
                coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num)
            # 更新券的剩余数量
            # coupon_id_list = my_models.CouponInfo.objects.update_num_by_type_num(c_type, user, num)
            coupon_id_list_base.extend(coupon_id_list)
            coupon_list_type.append({"coupon_id_list": coupon_id_list, "c_type": c_type, "num": num, "quota": quota})
        # 分开创建要不然 coupon_id_list 值跟预期的不一样（本来之前有立减券，如果新建的有效期短，那么就会优先用新的，可是本来不应该用新的）
        print(coupon_list_type, "coupon_list_type")
        for i in coupon_list_type:
            # 创建转赠记录(按券管理的数据对应，创建转赠记录)
            coupon_id_list = i.get("coupon_id_list")
            c_type = i.get("c_type")
            # 创建转赠记录
            give_instance = my_models.GiveRecord.objects.create_record(coupon_id_list, len(coupon_id_list), user,
                                                                       c_type, give_type=2, status=2)
            data = dict()
            data["id"] = give_instance.id  # 赠送id
            data["c_type"] = i.get("c_type")  # 类型
            data["num"] = i.get("num")  # 数量
            if c_type == 2:
                quota = "%.2f" % (float(i.get("quota")) / 100)  # 600 6元
            else:
                quota = "0"
            data["quota"] = quota  # 额度
            give_record_list.append(data)
        # 更新转赠记录
        my_models.CouponInfo.objects.filter(id__in=coupon_id_list_base).update(given=True)
        # 制作需要生成二维码的参数
        request_time = int(time.time() * 1000)
        params = str(give_record_list) + str(request_time) + str(user.id) + local_settings.SECRET_KEY
        sign = hashlib_md5(params)
        channel_key = user.coffee_channel.key if user.coffee_channel else "iamcoffee"
        return {"sign": sign, "give_record_list": give_record_list, "request_time": request_time,
                "share_user": user.id, "channel_key": channel_key}

    def update(self, instance, validated_data):
        pass

    class Meta:
        fields = ("user", "type_num",)


# 扫二维码领券
class ReceiveSerializers(serializers.Serializer):
    # param = serializers.CharField(label="参数", required=True, allow_null=False, error_messages={
    #     "required": "签名为必填项",
    #     "blank": "签名不能为空",
    # })
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    share_user = serializers.IntegerField(label="分享人id", required=True, allow_null=False, error_messages={
        "required": "分享人为必填项",
        "blank": "分享人不能为空",
    })
    give_record_list = serializers.ListField(label="类型数量json[{'type':1},{'num':1}]", help_text="类型数量json",
                                             write_only=True)
    sign = serializers.CharField(label="签名", required=True, allow_null=False, error_messages={
        "required": "签名为必填项",
        "blank": "签名不能为空",
    })
    request_time = serializers.CharField(label="时间戳", required=True, allow_null=False, error_messages={
        "required": "时间为必填项",
        "blank": "时间不能为空",
    })

    def validate_give_record_list(self, give_record_list):
        print(give_record_list, "give_record_list")
        own_user = self.initial_data["share_user"]
        record_list_id = []
        for i in give_record_list:
            record_list_id.append(i.get("id"))
        queryset = my_models.GiveRecord.objects.filter(id__in=record_list_id, own_user_id=own_user,
                                                       status=2).order_by("create_time")
        if queryset.exists():
            setattr(self, "record_queryset", queryset)
            return record_list_id
        else:
            raise serializers.ValidationError("已经被领取或对方已取消赠送")

    def validate_sign(self, sign):
        """
        :param attrs:
        :return:
        """
        request_time = self.initial_data["request_time"]
        give_record_list = self.initial_data["give_record_list"]
        own_user = self.initial_data["share_user"]
        params = str(give_record_list) + str(request_time) + str(own_user) + local_settings.SECRET_KEY
        print(params, "params")
        v_sign = hashlib_md5(params)
        if v_sign == sign:
            return True
        else:
            raise serializers.ValidationError("签名错误")

    def validate_share_user(self, share_user):
        if not share_user:
            raise serializers.ValidationError("分享人信息错误")
        if int(share_user) == self.context["request"].user.id:
            raise serializers.ValidationError("自己不能领自己的券")
        return share_user

    def validate_time(self, request_time):
        now_time = int(time.time() * 1000)
        if now_time - request_time > 3600 * 24 * 7:
            print("已过期")
            raise serializers.ValidationError("已过期")

    def validate(self, attrs):
        sign = attrs["sign"]
        give_record_list = attrs["give_record_list"]
        share_user = attrs["share_user"]
        request_time = attrs["request_time"]
        # self.validate_sign(sign)
        # self.validate_give_record_list(give_record_list)
        # self.validate_time(request_time)
        data = {
            "request_time": request_time,
            "share_user": share_user,
            "give_record_list": give_record_list,
            "sign": sign,
        }
        return data

    def create(self, validated_data):
        queryset = self.record_queryset
        print(queryset, "queryset")
        print(validated_data, "validated_data")
        user = self.context["request"].user
        coupon_id_list = []
        for i in queryset:
            i.status = 1
            i.receive_user = user
            i.save()
            my_models.GiveRecord.objects.create_record_by_after(i)
            coupon_id_list.extend(json.loads(i.coupon))
        # 用户领取了之后，将券变成用户，将赠送状态修改
        print(coupon_id_list, "coupon_id_list")
        my_models.CouponInfo.objects.filter(id__in=coupon_id_list).update(user=user, given=False)
        validated_data["coupon_id_list"] = coupon_id_list
        return validated_data

    def update(self, instance, validated_data):
        pass


class BaseSystemReceiveSerializers(serializers.Serializer):
    def validate_same_business_num(self, own_user):
        user = self.context["request"].user
        # create_time__lt=end_time, create_time__gte=now_time 同一天
        now_time = datetime.date.today()
        end_time = now_time + relativedelta(days=1)
        # own_user_id=own_user 同一个商家  receive_user:同一个人
        # 同一个人 同一天在同一个商家不能领取两次
        channel_key = own_user.mobile
        queryset = my_models.GiveRecord.objects.filter(own_user_id=own_user, receive_user=user,
                                                       create_time__lt=end_time,
                                                       create_time__gte=now_time, score=2)
        num = my_models.Channel.objects.get(key=channel_key).num
        if queryset.count() >= num:
            raise serializers.ValidationError("领取数量受限制，请明日再来")


# 扫系统二维码领券
class SystemReceiveSerializers(BaseSystemReceiveSerializers):
    param = serializers.CharField(label="参数", required=True, allow_null=False, error_messages={
        "required": "签名为必填项",
        "blank": "签名不能为空",
    })
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def validate_sign(self, attrs):
        """
        :param attrs:
        :return:
        """
        request_time = attrs["request_time"]
        params = str(request_time) + local_settings.SECRET_KEY
        v_sign = hashlib_md5(params)
        sign = attrs["sign"]
        print(v_sign, sign)
        if v_sign == sign:
            return True
        else:
            raise serializers.ValidationError("签名错误")

    def validate_time(self, request_time):
        # now_time = int(time.time() * 1000)
        # if now_time - request_time > 3600 * 24 * 100: # 时间 100天
        #     raise serializers.ValidationError("已过期")
        return request_time

    def validate_everyday_get_num(self):
        user = self.context["request"].user
        now_time = datetime.date.today()
        end_time = now_time + relativedelta(days=1)
        get_num = my_models.GiveRecord.objects.filter(receive_user=user, create_time__lt=end_time,
                                                      create_time__gte=now_time, score=2).count()
        if get_num >= 10:
            raise serializers.ValidationError("今天领取数量已超，请明天再来领取")

    def validate_num(self, give_record_list, own_user):
        c_id_list = []
        for i in give_record_list:
            num = i.get("num")
            c_type = i.get("c_type")
            # week_day = datetime.datetime.now().weekday()
            # if week_day == 1:  # 周二
            #     queryset = my_models.CouponInfo.objects.filter(c_type=c_type, user=own_user,quota=800,
            #                                                    used=False, expired=False).order_by("expire_time")
            # else:
            #     queryset = my_models.CouponInfo.objects.filter(c_type=c_type, user=own_user, quota=600,
            #                                                    used=False, expired=False).order_by("expire_time")
            print(own_user, "own_user")
            if c_type == 2:  # 如果是立减券面额越大越靠前
                queryset = my_models.CouponInfo.objects.filter(
                    c_type=c_type, user=own_user, used=False, expired=False).order_by("-quota", "expire_time")
            elif c_type == 9:  # 如果是兑换券面额越大越靠前
                queryset = my_models.CouponInfo.objects.filter(
                    c_type=c_type, user=own_user, used=False, expired=False).order_by("quota", "expire_time")
            else:
                queryset = my_models.CouponInfo.objects.filter(
                    c_type=c_type, user=own_user, used=False, expired=False).order_by("expire_time")
            id_list = queryset.values_list("id", flat=True)
            if len(id_list) > int(num):
                c_id_list.extend(id_list)
            else:
                raise serializers.ValidationError("数量不够了，明天再来吧")
        return c_id_list

    def create_pool_child_coupon(self, give_record_list, base_own_user, child_user):
        """
        :param give_record_list:
        :param base_own_user: 池子用户
        :param child_user: 小商家
        :return:
        """
        for i in give_record_list:
            num = i.get("num")
            c_type = i.get("c_type")
            coupon_list = my_models.CouponInfo.objects.filter(c_type=c_type, user=base_own_user, used=False,
                                                              expired=False).order_by("expire_time")[:int(num)]
            coupon_id_list = list(coupon_list.values_list("id", flat=True))
            # 将券queryset更新成接收人的
            my_models.CouponInfo.objects.filter(id__in=coupon_id_list).update(user=child_user, given=False)

    def _validate_active(self, user, active_key):
        """
        验证活动
        :return:
        """
        if my_models.CouponInfo.objects.filter(user=user, active_key=active_key).exists():
            raise serializers.ValidationError("已经领过此活动的券了")
        else:
            return True

    def validate(self, attrs):
        key = attrs["param"]
        user = self.context["request"].user
        from core.wchat.wx_base import mc
        value = mc.get(key)
        if not value:
            raise serializers.ValidationError("码失效了")
        else:
            data = json.loads(value)
            print(data, "coffee data")
            sign = data.get("sign")
            channel_key = data.get("channel_key")
            active_key = data.get("active_key")
            pool_key = data.get("pool_key")
            give_record_list = data.get("give_record_list")
            own_user = User.objects.get(mobile=channel_key)
            base_own_user = None
            if pool_key:  # 如果是池子数据
                base_own_user = User.objects.get(mobile=pool_key)
                # 验证还有没有池子数据
                self.validate_num(give_record_list, base_own_user)
            else:
                # 验证数量
                self.validate_num(give_record_list, own_user)
                if active_key:
                    self._validate_active(user, active_key)
            request_time = data.get("request_time")
            self.validate_sign(data)
            self.validate_time(request_time)
            # 验证同一个用户同一天领取十个商家
            self.validate_everyday_get_num()
            # 验证同一个商家每天只能领两次
            # own_user score=2
            self.validate_same_business_num(own_user)
            data = {
                "request_time": request_time,
                "sign": sign,
                "give_record_list": data.get("give_record_list"),
                "channel_key": data.get("channel_key"),
                "own_user": own_user,
            }
            if base_own_user is not None:
                data["base_own_user"] = base_own_user
            return data

    def create(self, validated_data):
        base_coupon_id_list = []
        user = self.context["request"].user
        # 创建转赠记录
        give_record_list = validated_data.get("give_record_list")
        own_user = validated_data.get("own_user")
        base_own_user = validated_data.get("base_own_user")
        if base_own_user:  # 给地下的商家创建券
            self.create_pool_child_coupon(give_record_list, base_own_user, own_user)
        for i in give_record_list:
            num = i.get("num")
            c_type = i.get("c_type")
            # 找到对应的券列表
            # week_day = datetime.datetime.now().weekday()
            # if week_day == 1:  # 周二
            #     coupon_list = my_models.CouponInfo.objects.filter(c_type=c_type, user=own_user, used=False, quota=800,
            #                                                       expired=False).order_by("expire_time")[:int(num)]
            # else:
            #     coupon_list = my_models.CouponInfo.objects.filter(c_type=c_type, user=own_user, used=False, quota=600,
            #                                                       expired=False).order_by("expire_time")[:int(num)]
            coupon_list = my_models.CouponInfo.objects.filter(c_type=c_type, user=own_user, used=False,
                                                              expired=False).order_by("expire_time")[:int(num)]
            coupon_id_list = list(coupon_list.values_list("id", flat=True))
            # 将券queryset更新成接收人的
            my_models.CouponInfo.objects.filter(id__in=coupon_id_list).update(user=user, given=False)
            # 创建券的记录
            my_models.GiveRecord.objects.create_record(coupon_id_list, num, own_user, c_type, give_type=2,
                                                       receive_user=user, score=2)
            base_coupon_id_list.extend(coupon_id_list)
        return base_coupon_id_list

    def update(self, instance, validated_data):
        pass


class H5CommitOrderSerializers(serializers.Serializer):
    vmc = serializers.CharField(label="vmc", required=True, allow_null=False, error_messages={
        "required": "vmc为必填项",
        "blank": "vmc不能为空",
    })
    pid = serializers.CharField(label="pid", required=True, allow_null=False, error_messages={
        "required": "pid为必填项",
        "blank": "pid不能为空",
    })
    orderNo = serializers.CharField(label="orderNo", required=True, allow_null=False, error_messages={
        "required": "orderNo为必填项",
        "blank": "orderNo不能为空",
    })
    price = serializers.CharField(label="price", required=True, allow_null=False, error_messages={
        "required": "price为必填项",
        "blank": "price不能为空",
    })
    fastcode = serializers.CharField(label="fastcode", required=True, allow_null=False, error_messages={
        "required": "fastcode为必填项",
        "blank": "fastcode不能为空",
    })
    mac = serializers.CharField(label="mac", required=True, allow_null=False, error_messages={
        "required": "mac为必填项",
        "blank": "mac不能为空",
    })
    page = serializers.CharField(label="page", required=True, allow_null=False, error_messages={
        "required": "page为必填项",
        "blank": "page不能为空",
    })

    # type_source = serializers.ChoiceField(default="wchatMini", choices=GiveRecordUrlSerializers.typeSource, label="来源",
    #                                       help_text="来源", write_only=True)

    def validate_mac(self, mac):
        """
        :param mac:
        :return:
        """
        vmc = self.initial_data["vmc"]
        fastcode = self.initial_data["fastcode"]
        price = self.initial_data["price"]
        pid = self.initial_data["pid"]
        orderNo = self.initial_data["orderNo"]
        user = "kalaibao"
        data = {"vmc": vmc, "fastcode": fastcode, "price": price, "pid": pid, "orderNo": orderNo, "user": user}
        param = "vmc={vmc}&pid={pid}&orderNo={orderNo}&price={price}&fastcode={fastcode}&user={user}".format(**data)
        if mac == hashlib_md5(param):
            return mac
        else:
            raise serializers.ValidationError("签名不正确")

    def validate(self, attrs):
        pid = attrs["pid"]
        coffee_instance = my_models.Coffee.objects.get(pid=pid)
        image = coffee_instance.image
        name = coffee_instance.name
        price = "%.2f" % (coffee_instance.price / 100.0)
        attrs["image"] = image
        attrs["name"] = name
        attrs["price"] = price
        return attrs

    def create(self, validated_data):
        from core.wchat.wx_base import mc
        key = uuid.uuid1().hex
        mc.set(key, json.dumps(validated_data), 3600 * 2)
        return key

    def update(self, instance, validated_data):
        pass


class ShareSerializers(DynamicFieldsModelSerializer):
    # create_time = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="创建时间", help_text="创建时间", read_only=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = my_models.UserShare
        fields = ("user",)

    def create(self, validated_data):
        user = validated_data.pop("user")
        user_id = user.id
        instance = my_models.UserShare.objects.get_or_create(user_id=user_id)
        return instance


class ReceiveSharedSerializers(DynamicFieldsModelSerializer):
    # create_time = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="创建时间", help_text="创建时间", read_only=True)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = my_models.ReceiveShared
        fields = ("share_id", "user",)

    def validate_share_id(self, share_id):
        try:
            share_instance = my_models.UserShare.objects.filter(user_id=share_id).first()
        except Exception as e:
            raise serializers.ValidationError("无效的分享用户")
        user = self.context["request"].user
        if user.id == share_id:
            raise serializers.ValidationError("不能领取自己的券哦")
        if my_models.ReceiveShared.objects.filter(share_id=share_id, user_id=user.id).exists():
            raise serializers.ValidationError("已领取过了哦")
        return share_id

    def create(self, validated_data):
        user = validated_data.pop("user")
        user_id = user.id
        validated_data["user_id"] = user_id
        instance = super().create(validated_data)
        # 分享领取人
        coupon_instance = my_models.CouponInfo.objects.one_create_by_normal(user, expire_days=7, quota=1000)
        my_models.GiveRecord.objects.create_record_by_system(1, 1, user, coupon=json.dumps([coupon_instance.id]))
        # 分享人
        share_instance = User.objects.get(id=validated_data["share_id"])
        coupon_instance = my_models.CouponInfo.objects.one_create_by_normal(share_instance, expire_days=7, quota=1000)
        my_models.GiveRecord.objects.create_record_by_system(1, 1, share_instance,
                                                             coupon=json.dumps([coupon_instance.id]))
        return instance


class UserInfoSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = User
        fields = ("id", "user", "mobile", "can_share_coupon")


class ReduceMoneyEveryDayActiveSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def validate(self, attrs):
        user = attrs.pop("user")
        attrs["user_id"] = user.id
        return attrs

    def create(self, validated_data):
        user_id = validated_data["user_id"]
        instance, created = my_models.ReduceMoneyEveryDayActive.objects.get_or_create(
            user_id=user_id
        )
        if created:
            today = datetime.date.today() - datetime.timedelta(days=1)
            my_models.ReduceMoneyEveryDay.objects.create(
                user_id=user_id,
                money=10,
                reduce_date=today,
            )
        return instance

    class Meta:
        model = my_models.ReduceMoneyEveryDayActive
        fields = ("user",)


# ------------------------------------------随机券-------------------------------------
# 生成随机券
class RandomCouponSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    # coupon = CouponSerializers(fields=("quota", "c_type",), read_only=True, many=False)
    # share_id = serializers.IntegerField(read_only=True, label="分享人id", help_text="分享人id")

    class Meta:
        model = my_models.RandomCouponRecord
        # fields = ("share_id", "user", "coupon", "id")
        fields = ("user", "id")

    def create(self, validated_data):
        user = self.context["request"].user
        if not user.can_share_coupon:
            raise serializers.ValidationError("不是有效的分享用户")
        instance = my_models.RandomCouponRecord.objects.create(
            share_id=user.id,
        )
        return instance


# 领取随机券
class UpdateRandomCouponSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    coupon = CouponSerializers(fields=("quota", "c_type",), read_only=True, many=False)
    share_id = serializers.IntegerField(read_only=True)

    class Meta:
        model = my_models.RandomCouponRecord
        fields = ("user", "coupon", "share_id")

    def _validate_instance(self, instance):
        share_id = instance.share_id
        user = self.context["request"].user
        if user.id == share_id:
            raise serializers.ValidationError("不能领取自己的券哦")
        try:
            if User.objects.get(id=share_id).can_share_coupon:
                pass
            else:
                raise serializers.ValidationError("不是有效的分享用户")
        except Exception as e:
            raise serializers.ValidationError("无效的分享用户")
        if instance.coupon:
            raise serializers.ValidationError("此券已经领取过了")
        today = datetime.date.today()
        start_time = datetime.datetime(today.year, today.month, today.day, 0, 0, 0)
        end_time = datetime.datetime(today.year, today.month, today.day, 23, 59, 59, 999)
        record_info = my_models.RandomCouponRecord.objects.filter(share_id=share_id, user_id=user.id,
                                                                  receive_time__gte=start_time,
                                                                  receive_time__lte=end_time)
        if record_info.exists():
            raise serializers.ValidationError("今天已经领过了")

    def update(self, instance, validated_data):
        self._validate_instance(instance)
        user = self.context["request"].user
        # quota = random.randrange(650, 950, 50)
        v = random.randint(1, 3)
        if v == 1:
            c_type = 7
            quota = 0
        elif v == 2:
            c_type = 2
            quota = 1500
        else:
            c_type = 2
            quota = 1700
        print(c_type, quota)
        coupon_instance = my_models.CouponInfo.objects.one_create_by_normal(user, expire_days=30, quota=quota,
                                                                            c_type=c_type)
        validated_data["coupon"] = coupon_instance
        validated_data["user_id"] = validated_data.pop("user").id
        validated_data["receive_time"] = datetime.datetime.now()
        instance = super(UpdateRandomCouponSerializers, self).update(instance, validated_data)
        return instance


# 固定码(上架)领取随机券
class CreateRandomCouponShopSerializers(BaseSystemReceiveSerializers):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    channel = serializers.CharField(label="参数", required=True, allow_null=False, error_messages={
        "required": "签名为必填项",
        "blank": "签名不能为空",
    })

    def validate(self, attrs):
        channel_key = attrs["channel"]
        own_user = User.objects.get(mobile=channel_key)
        self.validate_same_business_num(own_user)
        attrs["own_user"] = own_user
        return attrs

    def create(self, validated_data):
        own_user = validated_data["own_user"]
        coupon_list = my_models.CouponInfo.objects.filter(user=own_user, used=False, expired=False)
        coupon_id_list = list(coupon_list.values_list("id", flat=True))
        coupon_id = random.choice(coupon_id_list)
        user = self.context["request"].user
        # 将券queryset更新成接收人的
        obj = my_models.CouponInfo.objects.get(id=coupon_id)
        obj.user = user
        obj.given = False
        obj.save()
        # 创建券的记录
        my_models.GiveRecord.objects.create_record(coupon_id_list, 1, own_user, obj.c_type, give_type=2,
                                                   receive_user=user, score=2)
        return obj


# 购物车
class ShopCarSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.ShopCar
        fields = ("coffee_id", "num", "user_id",)


class ShopCarListSerializers(DynamicFieldsModelSerializer):
    update_time = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="创建时间", help_text="创建时间",
                                            read_only=True)
    coffee = CoffeeSerializers(many=False, fields=("id", "name", "price", "image", "pid",), label="coffee")

    class Meta:
        model = my_models.ShopCar
        fields = ("id", "coffee_id", "num", "user_id", "update_time")


class ShopCarUpdateSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.ShopCar
        fields = ("num", "status",)

    def update(self, instance, validated_data):
        validated_data["update_time"] = datetime.datetime.now()
        return super().update(instance, validated_data)


# -------------------------------------------季卡---------------------------------------
class CardBagSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.CardBag
        fields = "__all__"


class CardBagOrdersSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    goods_id = serializers.IntegerField(label="商品id", required=True, allow_null=False, error_messages={
        "required": "goods_id为必填项",
        "blank": "goods_id不能为空",
    })
    score = serializers.IntegerField(label="来源", required=True, allow_null=False, error_messages={
        "required": "score必填项",
        "blank": "score不能为空",
    })
    result = serializers.IntegerField(label="状态", help_text="状态", read_only=True)
    out_trade_no = serializers.CharField(label="订单号", help_text="订单号", read_only=True)
    goods = CardBagSerializers(fields=("name", "bank", "text_expire_time", "logo",), read_only=True, many=False)
    create_time = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="创建时间", help_text="创建时间",
                                            read_only=True)

    def validate(self, attrs):
        card_bag_id = attrs["goods_id"]
        try:
            card_bag_instance = my_models.CardBag.objects.get(id=card_bag_id)
        except Exception as e:
            raise serializers.ValidationError("商品id错误")
        payment = card_bag_instance.real_price
        goods_name = card_bag_instance.name
        attrs["payment"] = payment
        attrs["goods_name"] = goods_name
        return attrs

    class Meta:
        model = my_models.CardBagOrders
        fields = ("id", "score", "goods_id", "user", "result", "goods", "create_time", "out_trade_no")


class RefundCardBagOrdersSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    result = serializers.IntegerField(label="状态", help_text="状态", required=True)

    def validate_result(self, attrs):
        if attrs == 1 or attrs == "1":
            return attrs
        else:
            raise serializers.ValidationError("参数不对")

    def update(self, instance, validated_data):
        instance = super(RefundCardBagOrdersSerializers, self).update(instance, validated_data)
        total_fee = instance.payment
        refund_fee = total_fee
        out_refund_no = funcUtils.unique_value
        out_trade_no = instance.out_trade_no
        # 发起退款
        refund_notify_url = Config.host + "/coffee/api/refund_card_bag"
        status, e = RefundRecord.objects.wx_refund(total_fee, refund_fee, out_refund_no, out_trade_no,
                                                   notify_url=refund_notify_url, pay_type="mini")
        if not status:
            raise serializers.ValidationError(e)
        return instance

    class Meta:
        model = my_models.CardBagOrders
        fields = "__all__"


class RefundCardBagOrdersSerializersV2(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    result = serializers.IntegerField(label="状态", help_text="状态", required=True)

    def validate_result(self, attrs):
        if attrs == 1 or attrs == "1":
            return attrs
        else:
            raise serializers.ValidationError("参数不对")

    def update(self, instance, validated_data):
        instance = super(RefundCardBagOrdersSerializersV2, self).update(instance, validated_data)
        total_fee = instance.payment
        refund_fee = total_fee
        out_refund_no = funcUtils.unique_value
        out_trade_no = instance.out_trade_no
        # 发起退款
        refund_notify_url = Config.host + "/coffee/api/refund_card_bag"
        status, e = RefundRecord.objects.wx_refund_v2(total_fee, refund_fee, out_refund_no, out_trade_no,
                                                      notify_url=refund_notify_url, pay_type="mini")
        if not status:
            raise serializers.ValidationError(e)
        return instance

    class Meta:
        model = my_models.CardBagOrders
        fields = "__all__"


class UserCardBagSerializers(DynamicFieldsModelSerializer):
    cardbag = CardBagSerializers(many=False, fields=(
        "name", "price", "coupon_quota", "coupon_type", "coupon_num", "text_expire_time", "expire"
    ))
    unpacking_datetime = serializers.DateTimeField(format=API_DATETIME_FORMAT, label="拆包时间", help_text="拆包时间",
                                                   read_only=True)

    class Meta:
        model = my_models.UserCardBag
        exclude = ("user_id",)


class UpdateUserCardBagSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def validate_bag_status(self, bag_status):
        if self.instance.bag_status == 1:
            pass
        else:
            raise serializers.ValidationError("此卡包状态错误")
        if bag_status == 2:
            return bag_status
        else:
            raise serializers.ValidationError("不支持其他状态")

    class Meta:
        model = my_models.UserCardBag
        fields = ("user", "bag_status")

    def update(self, instance, validated_data):
        instance.unpacking()
        return instance


class UserBagRecordSerializers(DynamicFieldsModelSerializer):
    receive_user = serializers.SerializerMethodField()
    card_bag = CardBagSerializers(many=False, fields=("name", "card_type"), )

    def get_receive_user(self, instance):
        receive_user = instance.receive_user
        mobile = User.objects.get(id=receive_user).mobile
        return f"{mobile[0:3]}****{mobile[:-4]}"

    class Meta:
        model = my_models.CardBagRecord
        exclude = ("id",)


class UserBagRecordUpdateSerializers(DynamicFieldsModelSerializer):
    """
    领取分享卡包
    """
    receive_user = serializers.HiddenField(default=serializers.CurrentUserDefault)

    def update(self, instance, validated_data):
        receive_user = validated_data["receive_user"]
        receive_user = receive_user.id
        instance.update_receive_info(receive_user)
        user_card_bag = instance.user_card_bag
        user = self.context["requests"].user
        user_card_bag.update_user(user.id)
        return instance

    class Meta:
        model = my_models.CardBagRecord
        fields = ("receive_user",)


class UserBagRecordCreateSerializers(serializers.Serializer):
    user_card_bag_id = serializers.IntegerField(label="用户卡包id", help_text="用户卡包id")
    user = serializers.HiddenField(default=serializers.CurrentUserDefault)
    page = serializers.CharField(label="领取页面")
    type_source = serializers.CharField(label="类型", default="wchatMini")

    def validate_user_card_bag_id(self, user_card_bag_id):
        data = my_models.UserCardBag.objects.get(id=user_card_bag_id)
        if data.user_id != self.context["requests"].user.id:
            raise serializers.ValidationError("error")
        if data.giving:
            raise serializers.ValidationError("此卡包正在转增中")
        if data.bag_status == 1:
            return user_card_bag_id
        else:
            raise serializers.ValidationError("此卡包状态有问题")

    def create(self, validated_data):
        user_card_bag_id = validated_data["user_card_bag_id"]
        data = my_models.UserCardBag.objects.get(id=user_card_bag_id)
        record_instance = my_models.CardBagRecord.objects.create_bag_record(data)
        data.update_giving()
        return record_instance

    class Meta:
        fields = ("user_card_bag_id", "user", "page")


# -----------------------银行兑换券--------------------------
class BankExchangeCodeSerializers(DynamicFieldsModelSerializer):
    code = serializers.CharField(label="兑换码", help_text="兑换码", required=True, allow_blank=False)
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def validate_code(self, code):
        try:
            now_time = datetime.datetime.now()
            self.bank_code_instance = my_models.BankExchangeCode.objects.get(code=code, used=False,
                                                                             expire_time__gte=now_time)
        except Exception as e:
            raise serializers.ValidationError("无效的兑换码")
        return code

    def create(self, validated_data):
        bank_code_instance = self.bank_code_instance
        c_type = bank_code_instance.c_type
        user = self.context["request"].user
        quota = bank_code_instance.quota
        num = bank_code_instance.num
        expire_time = bank_code_instance.expire_time
        create_time = bank_code_instance.create_time
        channel = bank_code_instance.channel
        name = bank_code_instance.name
        my_models.CouponInfo.objects.bulk_create_by_normal(num, name, user, channel, expire_time,
                                                           create_time, c_type, quota=quota)
        bank_code_instance.used = True
        now_time = datetime.datetime.now()
        bank_code_instance.receive_time = now_time
        bank_code_instance.user_id = user.id
        bank_code_instance.save()
        return bank_code_instance

    class Meta:
        model = my_models.BankExchangeCode
        fields = ("user", "code",)


class ExchangeCodeRecordSerializers(DynamicFieldsModelSerializer):
    receive_time = serializers.DateTimeField(read_only=True, format=settings.API_DATETIME_FORMAT, help_text="领取时间",
                                             label="领取时间")
    quota = serializers.SerializerMethodField(read_only=True, label="额度", help_text="额度")

    def get_quota(self, instance):
        return "%.2f" % (instance.quota / 100)

    class Meta:
        model = my_models.BankExchangeCode
        fields = ("bank", "receive_time", "name", "num", "c_type", "quota")


class ReduceMoneyEveryDaySerializers(DynamicFieldsModelSerializer):
    reduce_date = serializers.DateField(format=settings.API_DATE_FORMAT)
    create_time = serializers.DateTimeField(format=settings.API_DATETIME_FORMAT)

    class Meta:
        model = my_models.ReduceMoneyEveryDay
        exclude = ("user_id",)


class ShopSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.ShopInfo
        fields = "__all__"


class H5ActiveSerializers(DynamicFieldsModelSerializer):
    h5_shop_set = ShopSerializers(many=True)

    class Meta:
        model = my_models.MakeH5
        fields = "__all__"


class MobileGetCouponSerializers(serializers.Serializer):
    key = serializers.CharField(required=True, label="key")
    mobile = serializers.CharField(required=True, max_length=11, min_length=11)

    class Meta:
        fields = "__all__"

    def validate_key(self, key):
        try:
            return my_models.MakeH5.objects.get(key=key)
        except Exception as e:
            raise serializers.ValidationError("key error")

    def update(self, instance, validated_data):
        pass

    def validate(self, attrs):
        h5_active_info = attrs["key"]
        # expire_time = h5_active_info.expire_time
        # channel = h5_active_info.channel
        mobile = attrs["mobile"]
        user_info, created = my_models.User.objects.get_or_create_user(mobile, coffee_channel=h5_active_info.channel)
        # user_info = User.objects.get(mobile=mobile)
        rules = h5_active_info.rules
        today = datetime.date.today()
        start_time = datetime.datetime(today.year, today.month, today.day, 0, 0, 0)
        end_time = datetime.datetime(today.year, today.month, today.day, 23, 59, 59, 999)
        if my_models.CouponInfo.objects.filter(h5_active=h5_active_info.key).count() >= h5_active_info.count:
            raise serializers.ValidationError("已经领完了。")
        if rules == 1:
            if my_models.CouponInfo.objects.filter(old_user_id=user_info.pk,
                                                   h5_active=h5_active_info.key).exists():
                raise serializers.ValidationError("已经领取过了")
        elif rules == 2:
            if my_models.CouponInfo.objects.filter(old_user_id=user_info.pk, h5_active=h5_active_info.key,
                                                   create_time__lte=end_time, create_time__gte=start_time).count() == 1:
                raise serializers.ValidationError("今天领取的数量以超出，请明天再来。")
        elif rules == 3:
            if my_models.CouponInfo.objects.filter(old_user_id=user_info.pk, h5_active=h5_active_info.key,
                                                   create_time__lte=end_time, create_time__gte=start_time).count() == 2:
                raise serializers.ValidationError("今天领取的数量以超出，请明天再来。")
        else:
            return attrs
        return attrs

    def create(self, validated_data):
        mobile = validated_data["mobile"]
        h5_active_info = validated_data["key"]
        channel = h5_active_info.channel
        receive_user, created = my_models.User.objects.get_or_create_user(mobile, coffee_channel=channel)
        num = h5_active_info.num
        expire_time = h5_active_info.expire_time
        expire_time = datetime.date.today() + relativedelta(days=expire_time + 1)
        c_type = h5_active_info.c_type
        quota = h5_active_info.quota
        c_name = h5_active_info.c_name
        create_time = datetime.datetime.now()
        my_models.CouponInfo.objects.bulk_create_by_normal(num, c_name, receive_user, channel, expire_time, create_time,
                                                           c_type, quota=quota, old_user_id=receive_user.id,
                                                           h5_active=h5_active_info.key)
        return h5_active_info


class InvoiceSerializers(DynamicFieldsModelSerializer):
    order_ids = serializers.ListField(write_only=True, label="订单编号")
    cash = serializers.HiddenField(default=0)
    username = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    format_cash = serializers.SerializerMethodField(label="金额")
    ready = serializers.BooleanField(label="已经开具", read_only=True)
    create_time = serializers.DateTimeField(label="创建时间", read_only=True, format=settings.API_DATETIME_FORMAT)
    full_name = serializers.CharField(label="名称")
    invoice_type = serializers.ChoiceField(choices=my_models.InvoiceInfo.invoiceType, default=1, write_only=True)
    card_num = serializers.CharField(label="税号", default="", required=False, allow_null=True, allow_blank=True)
    email_addr = serializers.CharField(label="邮箱")

    def validate_card_num(self, card_num):
        invoice_type = self.initial_data.get("invoice_type", 1)
        if int(invoice_type) == 1:
            if card_num:
                return card_num
            else:
                raise serializers.ValidationError("税号是必填项")
        else:
            return card_num

    def validate_cash(self, cash):
        order_ids = self.initial_data.get("order_ids", [])
        user = self.context["request"].user
        cash = my_models.CoffeeOrder.objects.invoice_orders_cash(order_ids, user)
        if cash:
            return cash
        else:
            raise serializers.ValidationError("没有可以开具发票的订单")

    def get_format_cash(self, instance):
        return "%.2f" % (instance.cash / 100)

    def validate_username(self, user):
        return user.username

    class Meta:
        fields = ("username", "cash", "order_ids", "format_cash", "ready", "create_time",
                  "full_name", "invoice_type", "card_num", "email_addr")
        model = my_models.InvoiceRecord

    def create(self, validated_data):
        instance = super().create(validated_data)
        order_ids = self.initial_data.get("order_ids", [])
        user = self.context["request"].user
        my_models.CoffeeOrder.objects.invoice_orders(order_ids, user).update(
            invoiced=1
        )
        return instance


class InvoiceInfoSerializers(DynamicFieldsModelSerializer):
    username = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    email_addr = serializers.CharField(default="", required=False)
    card_num = serializers.CharField(label="税号", default="", required=False, allow_null=True, allow_blank=True)

    def validate_username(self, user):
        return user.username

    def validate_card_num(self, card_num):
        invoice_type = self.initial_data.get("invoice_type", 1)
        if int(invoice_type) == 1:
            if card_num:
                return card_num
            else:
                raise serializers.ValidationError("税号是必填项")
        else:
            return card_num

    class Meta:
        model = my_models.InvoiceInfo
        fields = "__all__"

    def create(self, validated_data):
        username = validated_data["username"]
        if validated_data["is_default"]:
            my_models.InvoiceInfo.objects.filter(
                username=username
            ).update(
                is_default=False
            )
        return super(InvoiceInfoSerializers, self).create(validated_data)

    def update(self, instance, validated_data):
        username = validated_data["username"]
        if validated_data["is_default"]:
            my_models.InvoiceInfo.objects.filter(
                username=username
            ).update(
                is_default=False
            )
        return super(InvoiceInfoSerializers, self).update(instance, validated_data)


class ReceiveFreeCouponSerializers(serializers.Serializer):
    key = serializers.CharField()

    class Meta:
        fields = "__all__"

    def validate_key(self, key):
        """

        """
        data = mc.get(key)
        user = self.context["request"].user
        if data:
            data = json.loads(data)
            qr_code_now_time = data.get("now_time")
            now_time = int(time.time())
            queryset = my_models.CouponInfo.objects.can_use_coupon(user)
            instance = queryset.first()
            if instance:
                instance.given = True
                instance.save()
            else:
                raise serializers.ValidationError("券数量不足。请明天再领")
            data["coupon_instance"] = instance
            if now_time - qr_code_now_time > 15 * 60:
                raise serializers.ValidationError("码已经过期")
            else:
                return data
        else:
            raise serializers.ValidationError("被别人领走了")

    def create(self, validated_data):
        data = validated_data["key"]
        receive_user = self.context["request"].user
        coupon_instance = data.get("coupon_instance")
        coupon_id_list = [coupon_instance.pk]
        own_user_id = data.get("own_user_id")
        c_type = data["c_type"]
        coupon_num = data.get("num", 1)
        # 转增记录
        instance = self.create(
            own_user_id=own_user_id,
            receive_user=receive_user,
            c_type=c_type,
            num=coupon_num,
            give_type=5,  # 转增类型((1, "分享链接"), (2, "扫码"), (3, "手机号"), (4, "系统赠送"),  (5, "门店售货员")
            status=1,  # ((1, "已接收"), (2, "未接收"), (3, "已返回"),)
            score=1,  # ((1, "好友"), (2, "渠道"),)
            coupon=json.dumps(coupon_id_list)
        )
        # 更新
        coupon_instance.user = receive_user
        coupon_instance.given = False
        coupon_instance.save()
        return instance


class MakeFreeCouponSerializers(serializers.Serializer):
    c_type = serializers.IntegerField(label="类型")
    page = serializers.CharField(label="pageUrl")

    def validate_c_type(self, c_type):
        user = self.context["request"].user
        queryset = my_models.CouponInfo.objects.can_use_coupon(user)
        queryset = queryset.filter(c_type=c_type)
        if queryset.exists():
            return c_type
        else:
            raise serializers.ValidationError("券数量不足")

    class Meta:
        fields = ("c_type", "page",)

    def create(self, validated_data):
        now_time = int(time.time())
        c_type = 3  # 3 8 11
        data = {"now_time": now_time, "c_type": c_type, "mark": "ABC", "num": 1}
        params = json.dumps(data)
        key = uuid.uuid4().hex
        mc.set(key, params, 60 * 15)
        return key


class MemberListSerializers(DynamicFieldsModelSerializer):
    class Meta:
        model = my_models.MemberCenter
        fields = ("level", "expire_time", "url")


class MemberSerializers(serializers.Serializer):
    # level = serializers.IntegerField(label="类型", help_text="类型")
    # expire_day = serializers.IntegerField(label="有效期时间", help_text="有效期时间")
    Method = (
        (1, "扫码"), (2, "领取会员")
    )
    user = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    key = serializers.CharField(label="scene", help_text="scene")
    method = serializers.ChoiceField(label="方式", help_text="方式", default=2,
                                     choices=Method)

    class Meta:
        fields = ("user", "key", "method",)

    def validate(self, attrs):
        key = attrs.pop("key")
        scene_data = mc.get(key)
        scene_data = json.loads(scene_data)
        level = scene_data.get("level")
        attrs["level"] = level
        channel = scene_data.get("channel")
        expire_day = scene_data.get("expire")
        method = attrs.get("method")
        attrs["sign"] = channel
        attrs["expire_time"] = datetime.datetime.today() + datetime.timedelta(days=expire_day)
        attrs["create_time"] = datetime.datetime.now()
        if method == 1:
            return attrs
        user = attrs.pop("user")
        attrs["user_id"] = user.id
        attrs["mobile"] = user.mobile
        return attrs

    def create(self, validated_data):
        method = validated_data.pop("method")
        instance = my_models.MemberAddr.objects.get(
            level=validated_data["level"],
            sign=validated_data["sign"],
        )
        status = None
        if method == 2:
            qs = my_models.MemberCenter.objects.filter(
                expire_time=validated_data["expire_time"],
                level=validated_data["level"],
                user_id=validated_data["user_id"],
                mobile=validated_data["mobile"],
                sign=validated_data["sign"]
            )
            if not qs.exists():
                my_models.MemberCenter.objects.create(
                    **validated_data
                )
            else:
                member_instance = qs.first()
                if member_instance.finished:
                    status = 1  # 领取了开通了
                else:
                    status = 0  # 领取了未开通
        setattr(instance, "status", status)
        return instance


class ShowMemberSerializers(serializers.Serializer):
    key = serializers.CharField(label="scene", help_text="scene")

    class Meta:
        fields = ("key",)

    def validate(self, attrs):
        key = attrs.pop("key")
        scene_data = mc.get(key)
        scene_data = json.loads(scene_data)
        level = scene_data.get("level")
        channel = scene_data.get("channel")
        attrs["level"] = level
        attrs["sign"] = channel
        return attrs

    def create(self, validated_data):
        instance = my_models.MemberAddr.objects.get(
            level=validated_data["level"],
            sign=validated_data["sign"],
        )
        return instance


class ShareFriendSerializers(DynamicFieldsModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault(), write_only=True)
    share_id = serializers.IntegerField(label="分享人id", write_only=True)

    def validate_user(self, user):
        user_create_time = user.create_time
        v = datetime.datetime.now() - datetime.timedelta(minutes=30)
        if user.coffee_new_user and user_create_time < v:
            return user
        else:
            data = {"status":2, "message":"此活动只对新用户开放"}
            raise serializers.ValidationError(data)

    def create(self, validated_data):
        user = validated_data.pop("user")
        validated_data["user_id"] = user.id
        instance = super().create(validated_data)
        from .utils import share_data
        num, name, channel, expire_time, create_time, c_type, quota = share_data()
        my_models.CouponInfo.objects.bulk_create_by_normal(num, name, user, channel, expire_time, create_time, c_type,
                                                           quota=quota, can_share=False, is_laxin=True)  # 不让分享
        user.coffee_new_user = False
        user.save()
        return instance

    class Meta:
        model = my_models.ShareFriend
        fields = ("share_id", "user",)


class ShareFriendRecordSerializers(DynamicFieldsModelSerializer):
    mobile = serializers.SerializerMethodField(label="手机号")
    success_time = serializers.DateTimeField(format=API_DATETIME_FORMAT)

    def get_mobile(self, instance):
        user_id = instance.user_id
        user = User.objects.get(id=user_id)
        mobile = user.mobile[:3] + "****" + user.mobile[-4:]
        return mobile

    class Meta:
        model = my_models.ShareFriend
        fields = ("success_time", "mobile", )


class BankDiscountSerializers(DynamicFieldsModelSerializer):

    class Meta:
        model = my_models.BankDiscount
        exclude = ("user_id",)


class PayTitleSerializers(DynamicFieldsModelSerializer):

    class Meta:
        model = my_models.PayTitle
        exclude = ("client_id", "id", "show")